const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

class MyPromise {
  constructor(exector) {
    exector(this.resolve, this.reject);
  }
  //状态
  status = PENDING;
  value = undefined;
  reason = undefined;
  //成功回调存储
  successCallback = [];
  //失败回调存储
  failCallback = [];

  resolve = (value) => {
    if (this.status !== PENDING) return;
    this.status = FULFILLED;
    this.value = value;
    // this.successCallback && this.successCallback(value);
    while (this.successCallback.length) {
      this.successCallback.shift()();
    }
    return value;
  };

  reject = (reason) => {
    if (this.status !== PENDING) return;
    this.status = REJECTED;
    this.reason = reason;
    // this.failCallback && this.failCallback(reason)
    while (this.failCallback.length) {
      this.failCallback.shift()();
    }
    return reason;
  };

  then = (successCallback, failCallback) => {
    successCallback = successCallback ? successCallback : (value) => value;
    failCallback = failCallback
      ? failCallback
      : (reason) => {
          throw reason;
        };
    const newPromise = new Promise((resolve, reject) => {
      if (this.status === FULFILLED) {
        //变成异步是为了能拿到newPromise
        setTimeout(() => {
          //判断x的值是普通值还是promise对象
          //如果是普通值，则直接调用resolve
          //如果是promise对象，则查看promise对象返回的结果
          //再根据promise返回的结果，判断是调用resolve还是reject
          // resolve(x);
          let x = successCallback(this.value);
          resolvePromise(newPromise, x, resolve, reject);
        }, 0);
      } else if (this.status === REJECTED) {
        //变成异步是为了能拿到newPromise
        setTimeout(() => {
          //判断x的值是普通值还是promise对象
          //如果是普通值，则直接调用resolve
          //如果是promise对象，则查看promise对象返回的结果
          //再根据promise返回的结果，判断是调用resolve还是reject
          let x = failCallback(this.reason);
          resolvePromise(newPromise, x, resolve, reject);
        }, 0);
      } else {
        //等待
        this.successCallback.push(() => {
          //变成异步是为了能拿到newPromise
          setTimeout(() => {
            //判断x的值是普通值还是promise对象
            //如果是普通值，则直接调用resolve
            //如果是promise对象，则查看promise对象返回的结果
            //再根据promise返回的结果，判断是调用resolve还是reject
            // resolve(x);
            let x = successCallback(this.value);
            resolvePromise(newPromise, x, resolve, reject);
          }, 0);
        });
        this.failCallback.push(() => {
          //变成异步是为了能拿到newPromise
          setTimeout(() => {
            //判断x的值是普通值还是promise对象
            //如果是普通值，则直接调用resolve
            //如果是promise对象，则查看promise对象返回的结果
            //再根据promise返回的结果，判断是调用resolve还是reject
            let x = failCallback(this.reason);
            resolvePromise(newPromise, x, resolve, reject);
          }, 0);
        });
      }
    });
    return newPromise;
  };

  static all(array) {
    let result = [];
    let index = 0;
    return new MyPromise((resolve, reject) => {
      function addData(key, value) {
        result[key] = value;
        index++;
        if (index === array.length) {
          resolve(result);
        }
      }
      for (let i = 0; i < array.length; i++) {
        const current = array[i];
        if (current instanceof MyPromise) {
          //promise对象
          current.then(
            (value) => addData(i, value),
            (reason) => reject(reason)
          );
        } else {
          //普通值
          addData(i, array[i]);
        }
      }
    });
  }
}

function resolvePromise(newPromise, x, resolve, reject) {
  if (newPromise === x) {
    return reject(
      new TypeError("Chaining cycle detected for promise #<Promise>")
    );
  }
  if (x instanceof MyPromise) {
    x.then(resolve, reject);
  } else {
    resolve(x);
  }
}

module.exports = MyPromise;
